// bytes包提供了对字节切片进行读写操作的一系列函数，字节切片处理的函数比较多分为基本处理函数、比较函数、后缀检查函数、索引函数、
// 分割函数、大小写处理函数和子切片处理函数等。
package main

import (
	"bytes"
	"fmt"
)

func main() {
	var i int = 1
	var j byte = 2
	j = byte(i)
	fmt.Printf("j: %v\n", j)

	//Contains
	b := []byte("duoke360.com") //字符串强转为byte切片
	sublice1 := []byte("duoke360")
	sublice2 := []byte("DuoKe360")
	fmt.Println(bytes.Contains(b, sublice1)) //true
	fmt.Println(bytes.Contains(b, sublice2)) //false

	//Count
	s := []byte("hellooooooooo")
	sep1 := []byte("h")
	sep2 := []byte("l")
	sep3 := []byte("o")
	fmt.Println(bytes.Count(s, sep1)) //1
	fmt.Println(bytes.Count(s, sep2)) //2
	fmt.Println(bytes.Count(s, sep3)) //9

	//Repeat
	b = []byte("hi")
	fmt.Println(string(bytes.Repeat(b, 1))) //hi
	fmt.Println(string(bytes.Repeat(b, 3))) //hihihi

	//Replace
	s = []byte("hello,world")
	old := []byte("o")
	news := []byte("ee")
	fmt.Println(string(bytes.Replace(s, old, news, 0)))  //hello,world
	fmt.Println(string(bytes.Replace(s, old, news, 1)))  //hellee,world
	fmt.Println(string(bytes.Replace(s, old, news, 2)))  //hellee,weerld
	fmt.Println(string(bytes.Replace(s, old, news, -1))) //hellee,weerld

	//Runes
	s = []byte("你好世界")
	r := bytes.Runes(s)
	fmt.Println("转换前字符串的长度：", len(s)) //12
	fmt.Println("转换后字符串的长度：", len(r)) //4

	//Join
	s2 := [][]byte{[]byte("你好"), []byte("世界")}
	sep4 := []byte(",")
	fmt.Println(string(bytes.Join(s2, sep4))) //你好,世界
	sep5 := []byte("#")
	fmt.Println(string(bytes.Join(s2, sep5))) //你好#世界

}

//Buffer类型
//缓冲区是具有读取和写入方法的可变大小的字节缓冲区。Buffer的零值是准备使用的空缓冲区。 声明一个Buffer的四种方法：
/*var b bytes.Buffer // 直接定义一个Buffer变量，不用初始化，可以直接使用
b := new(bytes.Buffer) // 使用New返回Buffer变量
b := bytes.NewBuffer(s []byte) // 从一个[]byte切片，构造一个Buffer
b := bytes.NewBufferString(s string) // 从一个string变量，构造一个Buffer
往Buffer中写入数据
b.Write(d []byte) // 将切片d写入Buffer数据
b.WriteString(s string) // 将字符串s写入Buffer尾部
b.WriteByte(c byte) // 将字符c写入Buffer尾部
b.WriteRune(r rune) // 将一个rune类型的数据放到缓冲器的尾部
b.WriteTo(w io.Writer) // 将Buffer中的内容输出到实现了io.Writer接口的可写入对象中
注：将文件中的内容写入Buffer，则使用ReadFrom(i io.Reader)
从Buffer中读取数据到指定容器
c := make([]byte, 8)
b.Read(c) //一次读取8个byte到c容器中，每次读取新的8个byte覆盖c中原来的内容
b.ReadByte() //读取第一个byte，b的第一个byte被拿掉，赋值给 a => a, _ := b.ReadByte()
b.ReadRune() //读取第一个rune，b的第一个rune被拿掉，赋值给 r => r, _ := b.ReadRune()
b.ReadBytes(delimiter byte) //需要一个byte作为分隔符，读的时候从缓冲器里找第一个出现的分隔符（delim），找到后，把从缓冲器头部开始到分隔符之间的所有byte进行返回，作为byte类型的slice，返回后，缓冲器也会空掉一部分
b.ReadString(delimiter byte) //需要一个byte作为分隔符，读的时候从缓冲器里找第一个出现的分隔符（delim），找到后，把从缓冲器头部开始到分隔符之间的所有byte进行返回，作为字符串返回，返回后，缓冲器也会空掉一部分
b.ReadFrom(i io.Reader) //从一个实现io.Reader接口的r，把r里的内容读到缓冲器里，n返回读的数量

file, _ := os.Open(".text.txt")
buf := bytes.NewBufferString("Hello world")
buf.ReadFrom(file)
//将text.txt内容追加到缓冲器的尾部
fmt.Println(buf.String())
//清空数据
b.Reset()
//转换为字符串
b.String()
Reader类型
Reader实现了io.Reader, io.ReaderAt, io.WriterTo, io.Seeker, io.ByteScanner, io.RuneScanner接口，Reader是只读的、可以seek。
*/func testReader() {
	data := "123456789"
	//通过[]byte创建Reader
	re := bytes.NewReader([]byte(data))
	//返回未读取部分的长度
	fmt.Println("re len : ", re.Len())
	//返回底层数据总长度
	fmt.Println("re size : ", re.Size())
	fmt.Println("---------------")

	buf := make([]byte, 2)
	for {
		//读取数据
		n, err := re.Read(buf)
		if err != nil {
			break
		}
		fmt.Println(string(buf[:n]))
	}

	fmt.Println("----------------")

	//设置偏移量，因为上面的操作已经修改了读取位置等信息
	re.Seek(0, 0)
	for {
		//一个字节一个字节的读
		b, err := re.ReadByte()
		if err != nil {
			break
		}
		fmt.Println(string(b))
	}
	fmt.Println("----------------")

	re.Seek(0, 0)
	off := int64(0)
	for {
		//指定偏移量读取
		n, err := re.ReadAt(buf, off)
		if err != nil {
			break
		}
		off += int64(n)
		fmt.Println(off, string(buf[:n]))
	}
}
